package parserjc.jaccie;

import java.util.*;

/**
 * A Transition of a state of a automat of a scanner.
 *
 * @author Christoph Reich
 * @version 1.00 09.1997
 */
public class Transition {

/**
 * The follow state of this Transition
 */
private Integer followState;

/**
 * The list of guilty symbols as hash-codes as an area.
 * Example: d == hashcode 100 is valid because it is in [97-122]
 */
private Integer[][] hashSymbolList;

    /**
     * Constructs a new Transition.
     * @param symbols is the stringrepresentation of the valid symbols
     * @param followState the follow state of this transition
     */
    public Transition(String symbols, int followState) {
        this.followState = new Integer(followState);
        fillHashSymbolList(new StringTokenizer(symbols,","));
    }

    /**
     * Builds hash codes from the valid symbols and fill the
     * hashSymbolList.
     */
    private void fillHashSymbolList(StringTokenizer symbolList) {
        hashSymbolList = new Integer[symbolList.countTokens()][2];
        int counter = 0;
        while (symbolList.hasMoreTokens()) {
            String token = symbolList.nextToken();
            StringTokenizer rangeSymbols = new StringTokenizer(token,"-");
            Integer leftSide = new Integer (rangeSymbols.nextToken());
            Integer rightSide;
            if (rangeSymbols.hasMoreTokens())
                rightSide = new Integer(rangeSymbols.nextToken());
            else rightSide = leftSide;
            hashSymbolList[counter][0] = leftSide;
            hashSymbolList[counter][1] = rightSide;
            counter++;
        }
    }

    /**
     * Tests if a symbol is valid, means is inside the hashSymbolList
     * @return the followState if the symbol is valid else null
     * @param hashSymbol the testing symbol
     */
    public Integer testSymbol(Integer hashSymbol) {
        if (isInHashSymbolList(hashSymbol.intValue()))
            return followState;
        else return null;
    }

    /**
     * @return true, if the specified transition equals this transition.
     */
    public boolean equals(Transition transition) {
        if (this.toString().compareTo(transition.toString()) == 0
            && (followString()).compareTo(transition.followString()) == 0)
            return true;
        else return false;
    }

    /**
     * @return true, if the symbol is in the hashSymbolList
     * @param hashSymbol the testing symbol
     */
    private boolean isInHashSymbolList(int hashSymbol) {
        int left, right;
        for (int i=0; i < hashSymbolList.length; i++) {
            left = (hashSymbolList[i][0]).intValue();
            right = (hashSymbolList[i][1]).intValue();
            if (left <= hashSymbol && hashSymbol <= right)
                return true;
        }
        return false;
    }

    /**
     * @return the followState as a string.
     */
    public String followString() {
        return followState.toString();
    }

    /**
     * @return a string needed for building a java application
     */
    public String toString() {
        Integer left = hashSymbolList[0][0];
        Integer right= hashSymbolList[0][1];
        String symbols = left.toString();
        if (!left.equals(right))
            symbols += "-"+right.toString();
        for (int i=1; i < hashSymbolList.length; i++) {
            left = (hashSymbolList[i][0]);
            right = (hashSymbolList[i][1]);
            symbols += ","+left.toString();
            if (!left.equals(right))
                symbols += "-"+right.toString();
        }
        return symbols;
    }

}